package org.thunms.schedule.quartz.service;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javolution.util.FastList;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.thunms.framework.model.DataGrid;
import org.thunms.framework.model.DataGridJson;
import org.thunms.schedule.quartz.model.QrtzConstant;
import org.thunms.schedule.quartz.model.QrtzTriggers;


/**
 * 工作任务引擎
 * 任务管理子系统
 * 任务运行监控
 */
@Service
public class QrtzTriggersService implements Serializable  {
	private static final long serialVersionUID = 1256952256642891806L;
	private static final Logger logger=LoggerFactory.getLogger(QrtzTriggersService.class);
	@Autowired
	private JdbcTemplate jdbcTemplate;
	@Autowired
	@Qualifier("clusterQuartzScheduler")
	private Scheduler scheduler;
	public DataGridJson<QrtzTriggers> getDataGridList(DataGrid dg, QrtzTriggers mode) {
		DataGridJson<QrtzTriggers> dgs=new DataGridJson<QrtzTriggers>();
		List<QrtzTriggers> rows=FastList.newInstance();
		StringBuilder hql=new StringBuilder("select * from qrtz_triggers where 1=1 ");
		if(StringUtils.isNotBlank(mode.getTriggerName())){
			hql.append(" and trigger_name like'%").append(mode.getTriggerName()).append("%' ");
		}
		if(StringUtils.isNotBlank(mode.getTriggerGroup())){
			hql.append(" and trigger_group like'%").append(mode.getTriggerGroup()).append("%' ");
		}
		if(StringUtils.isNotBlank(dg.getSort())){
			if("triggerName".equals(dg.getSort())){
				hql.append(" order by trigger_name ").append(dg.getOrder());
			}else if("triggerGroup".equals(dg.getSort())){
				hql.append(" order by trigger_group ").append(dg.getOrder());
			}else if("nextFireTime".equals(dg.getSort())){
				hql.append(" order by next_fire_time ").append(dg.getOrder());
			}else if("prevFireTime".equals(dg.getSort())){
				hql.append(" order by prev_fire_time ").append(dg.getOrder());
			}else if("triggerState".equals(dg.getSort())){
				hql.append(" order by trigger_state ").append(dg.getOrder());
			}else{
				hql.append(" order by next_fire_time desc");	
			}
		}else{
			hql.append(" order by next_fire_time desc");
		}
		
		List<Map<String, Object>> entitys = jdbcTemplate.queryForList(hql.toString());
		long val = 0;
		if(entitys!=null){
			for (Map<String, Object> entity : entitys) {
				QrtzTriggers m=new QrtzTriggers();
				m.setId(UUID.randomUUID().toString());
				m.setTriggerName(MapUtils.getString(entity, "trigger_name".toUpperCase()));
				val = MapUtils.getLongValue(entity, "next_fire_time".toUpperCase());
				if(val>0){
					m.setNextFireTime(DateFormatUtils.format(val, "yyyy-MM-dd HH:mm:ss"));
				}
				val = MapUtils.getLongValue(entity, "prev_fire_time".toUpperCase());
				if(val>0){
					m.setPrevFireTime(DateFormatUtils.format(val, "yyyy-MM-dd HH:mm:ss"));
				}
				val = MapUtils.getLongValue(entity, "start_time".toUpperCase());
				if(val>0){
					m.setStartTime(DateFormatUtils.format(val, "yyyy-MM-dd HH:mm:ss"));
				}
				val = MapUtils.getLongValue(entity, "end_time".toUpperCase());
				if(val>0){
					m.setEndTime(DateFormatUtils.format(val, "yyyy-MM-dd HH:mm:ss"));
				}
				m.setTriggerState(QrtzConstant.status.get(MapUtils.getString(entity, "trigger_state".toUpperCase())));
				m.setTriggerGroup(MapUtils.getString(entity, "trigger_group".toUpperCase()));
				m.setPriority(MapUtils.getString(entity, "priority".toUpperCase()));
				m.setTriggerType(MapUtils.getString(entity, "trigger_type".toUpperCase()));
				//BeanUtils.copyProperties(entity, m);
				
				rows.add(m);
			}
		}
		dgs.setRows(rows);
		if(hql.lastIndexOf("order by")>0){
			hql.reverse().delete(0, hql.indexOf("yb redro")+8).reverse();	
		}
		dgs.setTotal(jdbcTemplate.queryForObject("select count(*) from qrtz_triggers", Long.class));
		return dgs;
	}
	
	
	/**
	 * 暂停任务所有
	 * @param jobIds
	 * @return
	 */
	public Boolean suspendAll(){
		try {
			scheduler.pauseAll();
		} catch (SchedulerException e) {
			return false;
		}
		return true;
		
	}
	/**
	 * 启动或恢复任务所有
	 * @param jobIds
	 * @return
	 */
	public Boolean recoveryAll(){
		try {
			scheduler.resumeAll();
		} catch (SchedulerException e) {
			return false;
		}
		return true;
		
	}
	/**
	 * 暂停任务
	 * @param jobIds
	 * @return
	 */
	public Boolean suspend(String triggerName,String triggerGroup){
		try {
			scheduler.pauseJob(new JobKey(triggerName,triggerGroup));
		} catch (SchedulerException e) {
			return false;
		}
		return true;
		
	}
	/**
	 * 启动或恢复任务
	 * @param jobIds
	 * @return
	 */
	public Boolean recovery(String triggerName,String triggerGroup){
		try {
			scheduler.resumeJob(new JobKey(triggerName, triggerGroup));
		} catch (SchedulerException e) {
			return false;
		}
		return true;
		
	}
	
	public Boolean deleteJob(String triggerName,String triggerGroup){
		try {
			//scheduler.deleteJob(new JobKey(triggerName,triggerGroup));
			scheduler.pauseTrigger(new TriggerKey(triggerName, triggerGroup));// 停止触发器  
			scheduler.unscheduleJob(new TriggerKey(triggerName, triggerGroup));// 移除触发器  
			scheduler.deleteJob(new JobKey(triggerName,triggerGroup));
			
		} catch (SchedulerException e) {
			return false;
		}
		return true;
		
	}
	/**
	 * 启动所有任务
	 * @return
	 */
	public Boolean startJobsAll(){
		try {
			if(!scheduler.isStarted()){
				scheduler.start();
			}
		} catch (SchedulerException e) {
			return false;
		}
		return true;
		
	}
	/**
	 * 关闭所有任务
	 * @return
	 */
	public Boolean shutdownJobsAll(){
		try {
			if (!scheduler.isShutdown()) {  
				scheduler.shutdown();  
            } 
		} catch (SchedulerException e) {
			return false;
		}
		return true;
		
	}

	/**
	 * 模拟执行
	 * @param triggerName
	 * @param triggerGroup
	 * @return
	 */
	public String simulatio(String triggerName, String triggerGroup) {
		try {
			TriggerKey tk=new TriggerKey(triggerName, triggerGroup);
			
			Trigger trigger=scheduler.getTrigger(tk);
			
			if(trigger instanceof CronTrigger ){
				CronTrigger cronTrigger=(CronTrigger)trigger;
				return CronExpressionTest.testCronExpression(cronTrigger.getCronExpression());
			}else if( trigger instanceof SimpleTrigger){
				return trigger.getDescription();
			}else{
				return "未识别的任务类型";
			}
			
		} catch (SchedulerException e) {
			return "模拟过程出现未知异常";
		}
	}

	/**
	 * 重新设定执行规则
	 * @param triggerName
	 * @param triggerGroup
	 * @param cronExpression
	 */
	public Boolean sdvancedAddSave(String triggerName, String triggerGroup,String cronExpression) {
		try {
			
		
			TriggerKey tk=new TriggerKey(triggerName, triggerGroup);
			
			Trigger trigger=scheduler.getTrigger(tk);
			
			if(trigger instanceof CronTrigger ){
				CronTrigger cronTrigger=(CronTrigger)trigger;
				
				String oldTime = cronTrigger.getCronExpression();  
		        if (!oldTime.equalsIgnoreCase(cronExpression)) {  
		            Trigger newtrigger = TriggerBuilder.newTrigger().withIdentity(triggerName,triggerGroup)
							.startAt(cronTrigger.getStartTime())
							.endAt(cronTrigger.getEndTime())
							.withDescription(cronTrigger.getDescription())
					        .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))  
					        .build();  
					scheduler.rescheduleJob(tk, newtrigger);
		        }  
				
			}
		 
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	
}
